---
sidebar_position: 10
---

# Interaction Modes

The interaction mode for a tree environment refers to how mouse inputs should interact with the tree.
The interaction mode can be provided as prop to the tree environment with the name `interactionMode` and needs
to follow [the `InteractionMode` enum](docs/api/enums/InteractionMode)
The following interaction modes are provided by default:

## `InteractionMode.ClickArrowToExpand`

:::note
See [the implementation of that interaction mode](https://github.com/lukasbach/react-complex-tree/blob/main/packages/core/src/interactionMode/ClickArrowToExpandInteractionManager.ts)
for more details.
:::

Clicking on items only moves focus. Pressing the CTRL key while clicking toggles the select state of the
clicked item. Expanding items is only possible by clicking on the arrow or via keyboard interactions.
Clicking on an item without children invokes the primary action for that item.

```jsx live
function App() {
  return (
    <UncontrolledTreeEnvironment
      dataProvider={new StaticTreeDataProvider(longTree.items, (item, data) => ({ ...item, data }))}
      getItemTitle={item => item.data}
      viewState={{}}
      defaultInteractionMode={'click-arrow-to-expand'}
    >
      <Tree treeId="tree-1" rootItem="root" treeLabel="Tree Example" />
    </UncontrolledTreeEnvironment>
  );
}
```

## `InteractionMode.ClickItemToExpand`

:::note
See [the implementation of that interaction mode](https://github.com/lukasbach/react-complex-tree/blob/main/packages/core/src/interactionMode/ClickItemToExpandInteractionManager.ts)
for more details.
:::

This is the default interaction mode. Clicking on items changes the select state to only the clicked item,
focuses the item and expands or collapses the item if it has children. Pressing the CTRL key while clicking toggles
the select state of the clicked item.
Clicking on an item without children invokes the primary action for that item.

This resembles the way how VSCode provides interactions with its tree view.

```jsx live
function App() {
  return (
    <UncontrolledTreeEnvironment
      dataProvider={new StaticTreeDataProvider(longTree.items, (item, data) => ({ ...item, data }))}
      getItemTitle={item => item.data}
      viewState={{}}
      defaultInteractionMode={'click-item-to-expand'}
    >
      <Tree treeId="tree-2" rootItem="root" treeLabel="Tree Example" />
    </UncontrolledTreeEnvironment>
  );
}
```

## `InteractionMode.DoubleClickItemToExpand`

:::note
See [the implementation of that interaction mode](https://github.com/lukasbach/react-complex-tree/blob/main/packages/core/src/interactionMode/DoubleClickItemToExpandInteractionManager.ts)
for more details.
:::

This is the default interaction mode. Clicking on items changes the select state to only the clicked item, but
does not expand or collapse parents or execute primary actions.
Double clicking an item expands or collapses parents and invokes primary actions on items without children.
Pressing the CTRL key while clicking toggles the select state of the clicked item.

This resembles the way of IntelliJ or other Jetbrain IDEs provides interactions with its tree view.

```jsx live
function App() {
  return (
    <UncontrolledTreeEnvironment
      dataProvider={new StaticTreeDataProvider(longTree.items, (item, data) => ({ ...item, data }))}
      getItemTitle={item => item.data}
      viewState={{}}
      defaultInteractionMode={'double-click-item-to-expand'}
    >
      <Tree treeId="tree-3" rootItem="root" treeLabel="Tree Example" />
    </UncontrolledTreeEnvironment>
  );
}
```

## Custom interaction modes

Instead of providing a string referring to the desired interaction mode, you can also provide a custom
interaction manager implementation which implements the [InteractionManager](/docs/api/interfaces/InteractionManager)
implementation.

Essentially, it needs to implement a `createInteractiveElementProps` method which provides HTML props for
a interactive tree item node. Look [into the API](/docs/api/interfaces/InteractionManager) to see which
parameters are available as arguments.

The best way to get started is to look into the
[implementations of existing interaction modes](https://github.com/lukasbach/react-complex-tree/tree/main/packages/core/src/interactionMode),
to see which props you should implement.

The following example shows a custom very simple interaction mode which only focuses items when clicking on them,
but never selects them.

```jsx live
function App() {
  return (
    <UncontrolledTreeEnvironment
      dataProvider={new StaticTreeDataProvider(longTree.items, (item, data) => ({ ...item, data }))}
      getItemTitle={item => item.data}
      defaultInteractionMode={{
        mode: 'custom',
        createInteractiveElementProps: (item, treeId, actions, renderFlags) => ({
          onClick: e => {
            actions.focusItem();
          },
          onFocus: () => {
            actions.focusItem();
          },
          tabIndex: !renderFlags.isRenaming ? (renderFlags.isFocused ? 0 : -1) : undefined,
        }),
      }}
      viewState={{
        ['tree-4']: {
          expandedItems: ['Fruit', 'Meals'],
        },
      }}
    >
      <Tree treeId="tree-4" rootItem="root" treeLabel="Tree Example" />
    </UncontrolledTreeEnvironment>
  );
}
```

Typically, you don't want to implement the complete interaction manager yourself. You can specify one
of the default interaction modes that you want to extend with the `extend` prop:

```jsx live
function App() {
  return (
    <UncontrolledTreeEnvironment
      dataProvider={new StaticTreeDataProvider(longTree.items, (item, data) => ({ ...item, data }))}
      getItemTitle={item => item.data}
      defaultInteractionMode={{
        mode: 'custom',
        extends: 'click-item-to-expand',
        createInteractiveElementProps: (item, treeId, actions, renderFlags) => ({
          onMouseOver: () => {
            document
              .querySelectorAll(`[data-rct-tree="tree-5"] [data-rct-item-id]`)
              .forEach(element => (element.style.background = 'transparent'));
            document.querySelector(`[data-rct-tree="tree-5"]  [data-rct-item-id="${item.index}"]`).style.background =
              'red';
          },
        }),
      }}
      viewState={{
        ['tree-5']: {
          expandedItems: ['Fruit', 'Meals'],
        },
      }}
    >
      <Tree treeId="tree-5" rootItem="root" treeLabel="Tree Example" />
    </UncontrolledTreeEnvironment>
  );
}
```

## Completely omitting interaction modes

The interaction mode defines, how the `interactiveElementProps` prop is created for rendering the interactive
element of an tree item. The prop can also easily be omitted in custom render implementations and individual DOM
interactions can be defined instead.
[Look into the documentation on custom render hooks](/docs/guides/rendering) to find out more.
